package it.infodea.tapestrydea.components.jcr;

import it.infodea.tapestrydea.services.jcr.JcrWorkspaceService;
import it.infodea.tapestrydea.services.jcr.nodes.wrappers.JcrFileNode;

import java.util.List;

import javax.jcr.PathNotFoundException;
import javax.jcr.RepositoryException;

import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentEventCallback;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.annotations.BeginRender;
import org.apache.tapestry5.annotations.IncludeStylesheet;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Path;
import org.apache.tapestry5.internal.util.Holder;
import org.apache.tapestry5.ioc.annotations.Inject;

@IncludeStylesheet("FilesNavigator.css")
public class FilesNavigator {

	public static final String SELECT_FILE_EVENT = "selectFile";
	public static final String DELETE_FILE_EVENT = "dleteFile";
	public static final String CHECKOUT_FILE_EVENT = "checkoutFile";
	public static final String UNDO_CHECKOUT_FILE_EVENT = "undoCheckoutFile";
	public static final String CHECKIN_FILE_EVENT = "checkinFile";
	private static final String INTERNAL_SELECT_FILE_EVENT_NAME = "filesNavigator_selectFile";
	private static final String INTERNAL_CHECK_IN_EVENT_NAME = "filesNavigator_checkInFile";
	private static final String INTERNAL_CHECK_OUT_EVENT_NAME = "filesNavigator_checkOutFile";
	private static final String INTERNAL_UNDO_CHECK_OUT_EVENT_NAME = "filesNavigator_undoCheckOutFile";
	private static final String INTERNAL_DELETE_FILE_EVENT_NAME = "filesNavigator_deleteFile";

	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/file.png")
	private Asset fileImage;
	
	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/content_checkout.png")
	private Asset checkOutImage;
	
	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/content_checkout-undo.png")
	private Asset checkOutUndoImage;
	
	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/content_checkin.png")
	private Asset checkInImage;
	
	@Inject
	@Path("classpath:/it/infodea/tapestrydea/components/jcr/delete.png")
	private Asset deleteImage;
	
	@Parameter(name="folderPath")
	private String parentPath;

	private JcrFileNode file;

	private List<JcrFileNode> files;

	@Inject
	private ComponentResources _resources;
	
	@Inject
	private JcrWorkspaceService service;
	
	@BeginRender
	void setup() throws RepositoryException{
		if(parentPath == null){
			parentPath = "/";
		}
		files = service.getFolder(parentPath).getFiles();
	}
	
	@OnEvent(INTERNAL_SELECT_FILE_EVENT_NAME)
	Object changePath(String uuid) throws PathNotFoundException, RepositoryException{
		JcrFileNode file = service.getFileByUUID(uuid);
		if(file != null){
			return triggerEvent(SELECT_FILE_EVENT ,file);
		}
		return null;
	}
	
	@OnEvent(INTERNAL_DELETE_FILE_EVENT_NAME)
	Object deleteFile(String uuid) throws PathNotFoundException, RepositoryException{
		JcrFileNode file = service.getFileByUUID(uuid);
		if(file != null){
			return triggerEvent(DELETE_FILE_EVENT ,file);
		}
		return null;
	}
	
	@OnEvent(INTERNAL_CHECK_OUT_EVENT_NAME)
	Object checkOut(String uuid) throws PathNotFoundException, RepositoryException{
		JcrFileNode file = service.getFileByUUID(uuid);
		if(file != null){
			return triggerEvent(CHECKOUT_FILE_EVENT ,file);
		}
		return null;
	}
	
	@OnEvent(INTERNAL_UNDO_CHECK_OUT_EVENT_NAME)
	Object undoCheckOut(String uuid) throws PathNotFoundException, RepositoryException{
		JcrFileNode file = service.getFileByUUID(uuid);
		if(file != null){
			return triggerEvent(UNDO_CHECKOUT_FILE_EVENT ,file);
		}
		return null;
	}
	
	@OnEvent(INTERNAL_CHECK_IN_EVENT_NAME)
	Object checkIn(String uuid) throws PathNotFoundException, RepositoryException{
		JcrFileNode file = service.getFileByUUID(uuid);
		if(file != null){
			return triggerEvent(CHECKIN_FILE_EVENT ,file);
		}
		return null;
	}
	
	private Object triggerEvent(String eventName, JcrFileNode file){
		final Holder<Object> resultHolder = Holder.create();

		ComponentEventCallback<Object> handler = new ComponentEventCallback<Object>() {

			public boolean handleResult(Object result) {
				resultHolder.put(result.toString());
				return true;
			}
		};

		_resources.triggerEvent(eventName, new Object[] { file },
				handler);
		
		return resultHolder.get();
	}
	
	public Asset getFileImage() {
		return fileImage;
	}

	public Asset getCheckInImage() {
		return checkInImage;
	}
	
	public Asset getCheckOutImage() {
		return checkOutImage;
	}
	
	public Asset getDeleteImage() {
		return deleteImage;
	}
	
	public Asset getCheckOutUndoImage() {
		return checkOutUndoImage;
	}
	
	public boolean isCheckedOut() throws RepositoryException {
		return file.isCheckedOut();
	}
	
	public JcrFileNode getFile() {
		return file;
	}

	public void setFile(JcrFileNode file) {
		this.file = file;
	}

	public List<JcrFileNode> getFiles() {
		return files;
	}
}
